package com.utils.worldcup;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.utils.bfs.Graph;

import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

public class WorldCupOrderUtils {

    private static class SingletonHolder {
        private static final WorldCupOrderUtils INSTANCE = new WorldCupOrderUtils();

    }

    private WorldCupOrderUtils() {

    }

    public static WorldCupOrderUtils getInstance() {
        return WorldCupOrderUtils.SingletonHolder.INSTANCE;
    }


    public Map<String, Object> getOrder(int win, int lost, int pp, int win2, int lost2, int pp2, List<String> groupA, String[] eventA, double[] scoreA, double[] scoreB) {
        Map<String, Object> resultMap = new HashMap<>();
        // 所有选项集合
        LinkedList<String[]> list = new LinkedList<>();
        // 每个路线对应事件
        Map<String, String> map = new HashMap<>();
        Map<String, String> totalScore = new HashMap<>();

        List<String> allLine = new ArrayList<>();
        //初始化根节点
        Graph theGraph = new Graph();
        String[] opArr = new String[]{"#"};
        list.add(opArr);
        //初始化事件分支
        for (int i = 0; i < eventA.length; i++) {
            String label = eventA[i];
            cg(label, (i + 1), map, list);
        }
        //根节点以及中间节点
        for (int i = 0; i < list.size(); i++) {
            if (i + 1 == list.size()) {
                break;
            }
            String[] a1 = list.get(i);
            String[] a2 = list.get(i + 1);
            addEdge(theGraph, a1, a2);
        }
        String[] last = list.getLast();
        //叶子节点
        for (String aLast : last) {
            theGraph.addVertex(aLast);
        }

        StringBuilder sb = new StringBuilder();
        List<List<String>> allPathList = theGraph.mst();
        for (List<String> onePath : allPathList) {
            if (sb.length() > 0) {
                sb.delete(0, sb.length());
            }
            for (String node : onePath) {
                sb.append(node).append(",");
            }
            String options = sb.substring(2, sb.length() - 1);
            allLine.add(options);
        }
        for (String line : allLine) {
            String[] all = line.split(",");
            for (String cg : all) {
                String end = map.get(cg);
                String vStr = totalScore.get(line);
                double v;
                if (null == vStr) {
                    v = 1.0;
                } else {
                    v = Double.parseDouble(vStr);
                }
                if (end.endsWith("平")) {
                    String[] op = end.replace("平", "").split("VS");
                    int index = groupA.indexOf(op[0].trim());
                    if (index == 0) {
                        v *= scoreB[index] * pp;
                    } else {
                        // 说明是第二场
                        v *= scoreB[index];
                    }
                } else if (end.endsWith("主胜")) {
                    String[] op = end.replace("主胜", "").split("VS");
                    int index = groupA.indexOf(op[0].trim());
                    if (index == 0) {
                        v *= scoreA[index] * win;
                    } else if (index == 2) {
                        v *= scoreA[index];
                    }
                } else if (end.endsWith("客胜")) {
                    String[] op = end.replace("客胜", "").split("VS");
                    int index = groupA.indexOf(op[1].trim());
                    if(index == 1){
                        v *= scoreA[index] * lost;
                    } else if(index == 3){
                        v *= scoreA[index];
                    }
                }
                totalScore.put(line, String.format("%.2f", v));
            }

        }
        StringBuilder result = new StringBuilder();
        result.append("最近有").append(eventA.length).append("场比赛\n");
        for (String e : eventA) {
            double a = getV(e + "主胜", groupA, scoreA, scoreB);
            double b = getV(e + "平", groupA, scoreA, scoreB);
            double c = getV(e + "客胜", groupA, scoreA, scoreB);
            result.append(e).append("\n[胜平负赔率/").append(a).append("/").append(b).append("/").append(c).append("]\n");
        }
        result.append("\n下注方案2串1：\n");
        List<Integer> list1 = Lists.newArrayList(win,lost,pp);
        List<Integer> collect1 = list1.stream().filter(a -> a > 0).collect(Collectors.toList());
        List<Integer> list2 = Lists.newArrayList(win2,lost2,pp2);
        List<Integer> collect2 = list2.stream().filter(a -> a > 0).collect(Collectors.toList());
        int cp = collect1.size() * collect2.size();
        Integer cc = collect1.get(0);
        result.append(groupA.get(0)).append("胜 下注").append(win>0?"√":"×").append("\n");
        result.append(eventA[0]).append("平 下注").append(pp>0?"√":"×").append("\n");
        result.append(groupA.get(1)).append("胜 下注").append(lost>0?"√":"×").append("\n");

        result.append(groupA.get(2)).append("胜 下注").append(win2>0?"√":"×").append("\n");
        result.append(eventA[1]).append("平 下注").append(pp2>0?"√":"×").append("\n");
        result.append(groupA.get(3)).append("胜 下注").append(lost2>0?"√":"×").append("\n");
        result.append("\n下注金额：").append(cc).append("元、总成本共").append(cp * cc).append("元\n");
        result.append("\n获奖结局情况如下：\n");
        totalScore.forEach((k, v) -> {
            if (win == 0 && k.contains("W1")) {
                return;
            }
            if (lost == 0 && k.contains("L1")) {
                return;
            }
            if (pp == 0 && k.contains("D1")) {
                return;
            }
            if (win2 == 0 && k.contains("W2")) {
                return;
            }
            if (lost2 == 0 && k.contains("L2")) {
                return;
            }
            if (pp2 == 0 && k.contains("D2")) {
                return;
            }
            result.append(k).append(" = ").append(v).append("元\n");

        });
        result.append("\n备注：\n");
        map.forEach((k, v) -> result.append(k).append(" 代表 ").append(v).append("\n"));
        result.append("注意：该方案事先把弱队顺序调整到客胜\n计算赔率情况下考虑所有的获奖结局");
        resultMap.put("result", result.toString());
        resultMap.put("cost", (cp * cc));
        return resultMap;
    }


    private static double getV(String end, List<String> groupA, double[] scoreA, double[] scoreB) {
        double v = 0.0;
        if (end.endsWith("平")) {
            String[] op = end.replace("平", "").split("VS");
            v = scoreB[groupA.indexOf(op[0].trim())];
        } else if (end.endsWith("主胜")) {
            String[] op = end.replace("主胜", "").split("VS");
            v = scoreA[groupA.indexOf(op[0].trim())];
        } else if (end.endsWith("客胜")) {
            String[] op = end.replace("客胜", "").split("VS");
            v = scoreA[groupA.indexOf(op[1].trim())];
        }
        return v;
    }


    /**
     * 添加子节点
     */
    private static void addEdge(Graph theGraph, String[] a1, String[] a2) {
        for (String root : a1) {
            //添加叶子根
            theGraph.addVertex(root);
            //再给叶子根添加子节点
            for (String anA2 : a2) {
                theGraph.addEdge(root, anA2);
            }

        }
    }

    /**
     * 分支事件
     */
    private static void cg(String label, int count, Map<String, String> map, LinkedList<String[]> list) {
        String g1 = "W" + count;
        String g2 = "D" + count;
        String g3 = "L" + count;
        map.put(g1, label + " 主胜");
        map.put(g2, label + " 平");
        map.put(g3, label + " 客胜");
        String[] opArr;
        List<String> opCount = Lists.newArrayList(g1, g2, g3);
        opArr = new String[opCount.size()];
        opArr = opCount.toArray(opArr);
        list.add(opArr);
    }

}
